/*******************************************************************************
 * Copyright (c) 2008-2009 zhang yuexiang.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package org.xfeep.asura.bootstrap.config.test;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;

import javax.xml.parsers.ParserConfigurationException;


import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.xfeep.asura.bootstrap.Asura;
import org.xfeep.asura.bootstrap.MemoryComponentLoader;
import org.xfeep.asura.bootstrap.config.XmlDirConfigLoader;
import org.xfeep.asura.bootstrap.config.XmlMultipleConfigLoader;
import org.xfeep.asura.core.ComponentContext;
import org.xfeep.asura.core.ServiceSpace;
import org.xfeep.asura.core.annotation.Activate;
import org.xfeep.asura.core.annotation.Config;
import org.xfeep.asura.core.annotation.Property;
import org.xfeep.asura.core.annotation.Service;
import org.xfeep.asura.core.config.ConfigAdminService;
import org.xfeep.asura.core.util.InlineExecutorService;
import org.xml.sax.SAXException;


public class AsuraBootstrapWithLoadConfigTestSet {

	Asura asura;
	
	@Before
	public void setUp() throws Exception {
		asura = new Asura(); //new URLClassLoader(new URL[]{new File("bin").toURI().toURL()})
		asura.setExecutorService(new InlineExecutorService());
	}
	
	
	@Config("http")
	@Service
	public static class MyHttpServer {
		
	    @Property
		int port;
	    @Property
	    String serverName;
	    @Property
	    int maxThread;
	    @Property
	    int minThread; 
	    @Property
	    int sessionTimeout;
	    
	    @Activate
	    public void start(ComponentContext ctx) {
	    	System.out.println("I start now! " + ctx.getProperties());
	    }
	    
	}
	
	@Test
	public void testSimpleConfigLoad() {
		asura.start(new MemoryComponentLoader(), new MemoryComponentLoader(MyHttpServer.class));
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		ConfigAdminService configAdmin = appServiceSpace.findService(ConfigAdminService.class);
		configAdmin.load(new XmlDirConfigLoader("testconf/xmls"));
		MyHttpServer myHttpServer = appServiceSpace.findService(MyHttpServer.class);
		assertEquals("MyHttpServer", myHttpServer.serverName);
		assertEquals(8080, myHttpServer.port);
		assertEquals(5, myHttpServer.maxThread);
		assertEquals(2, myHttpServer.minThread);
		assertEquals(300, myHttpServer.sessionTimeout);
	}
	
	public static class HttpServerInfo {
		
		int port;
	    String serverName;
	    int maxThread;
	    int minThread; 
	    int sessionTimeout;
	    
	    
	}
	
	@Config("MyHttpServerList")
	@Service
	public static class ServiceWithListXmlConfig {
		
		@Property
		List<HttpServerInfo> myhttpServerList; 
		
		@Property
		String name;
		
		 @Activate
		 public void start(ComponentContext ctx) {
		    	System.out.println("I start now! " + ctx.getProperties());
		 }		
		
	}
	
	@Test
	public void testListConfigLoad() {
		asura.start(new MemoryComponentLoader(), new MemoryComponentLoader(ServiceWithListXmlConfig.class));
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		ConfigAdminService configAdmin = appServiceSpace.findService(ConfigAdminService.class);
		configAdmin.load(new XmlDirConfigLoader("testconf/xmls"));
		ServiceWithListXmlConfig serviceWithListXmlConfig = appServiceSpace.findService(ServiceWithListXmlConfig.class);
		assertEquals("MyHttpServerListTest", serviceWithListXmlConfig.name);
		assertEquals(2, serviceWithListXmlConfig.myhttpServerList.size());
		for (int i = 0; i < 2; i++){
			HttpServerInfo myHttpServer = serviceWithListXmlConfig.myhttpServerList.get(i);
			assertEquals("MyHttpServer_" + (i+1), myHttpServer.serverName);
			assertEquals(8080 + i + 1, myHttpServer.port);
			assertEquals(i+1, myHttpServer.maxThread);
			assertEquals(i+1, myHttpServer.minThread);
			assertEquals(300 + (i+1), myHttpServer.sessionTimeout);
		}
		
	}
	
	
	@Config("MyHttpServerArray")
	@Service
	public static class ServiceWithArrayXmlConfig {
		
		@Property
		HttpServerInfo[] myhttpServerArray; 
		
		@Property
		String name;
		
		 @Activate
		 public void start(ComponentContext ctx) {
		    	System.out.println("I start now! " + ctx.getProperties());
		 }		
		
	}
	
	@Test
	public void testArrayConfigLoad() {
		asura.start(new MemoryComponentLoader(), new MemoryComponentLoader(ServiceWithArrayXmlConfig.class));
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		ConfigAdminService configAdmin = appServiceSpace.findService(ConfigAdminService.class);
		configAdmin.load(new XmlDirConfigLoader("testconf/xmls"));
		ServiceWithArrayXmlConfig serviceWithArrayXmlConfig = appServiceSpace.findService(ServiceWithArrayXmlConfig.class);
		assertEquals("MyHttpServerArrayTest", serviceWithArrayXmlConfig.name);
		assertEquals(2, serviceWithArrayXmlConfig.myhttpServerArray.length);
		for (int i = 0; i < 2; i++){
			HttpServerInfo myHttpServer = serviceWithArrayXmlConfig.myhttpServerArray[i];
			assertEquals("MyHttpServer_" + (i+1), myHttpServer.serverName);
			assertEquals(8080 + i + 1, myHttpServer.port);
			assertEquals(i+1, myHttpServer.maxThread);
			assertEquals(i+1, myHttpServer.minThread);
			assertEquals(300 + (i+1), myHttpServer.sessionTimeout);
		}
		
	}
	
	@Config("MyHttpServerMap")
	@Service
	public static class ServiceWithMapXmlConfig {
		
		@Property
		Map<String, HttpServerInfo> myhttpServerMap; 
		
		@Property
		String name;
		
		 @Activate
		 public void start(ComponentContext ctx) {
		    	System.out.println("I start now! " + ctx.getProperties());
		 }		
		
	}
	
	
	@Test
	public void testMapConfigLoad() {
		asura.start(new MemoryComponentLoader(), new MemoryComponentLoader(ServiceWithMapXmlConfig.class));
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		ConfigAdminService configAdmin = appServiceSpace.findService(ConfigAdminService.class);
		configAdmin.load(new XmlDirConfigLoader("testconf/xmls"));
		ServiceWithMapXmlConfig serviceWithMapXmlConfig = appServiceSpace.findService(ServiceWithMapXmlConfig.class);
		assertEquals("MyHttpServerListTest", serviceWithMapXmlConfig.name);
		assertEquals(2, serviceWithMapXmlConfig.myhttpServerMap.size());
		for (int i = 0; i < 2; i++){
			HttpServerInfo myHttpServer = serviceWithMapXmlConfig.myhttpServerMap.get("MyHttpServer_" + (i+1));
			assertEquals("MyHttpServer_" + (i+1), myHttpServer.serverName);
			assertEquals(8080 + i + 1, myHttpServer.port);
			assertEquals(i+1, myHttpServer.maxThread);
			assertEquals(i+1, myHttpServer.minThread);
			assertEquals(300 + (i+1), myHttpServer.sessionTimeout);
		}
		
	}
	
	@Config("MyHttpServerProperties")
	@Service
	public static class ServiceWithJavaUtilPropertiesXmlConfig {
		
		@Property
		Properties myHttpProperties; 
		
		@Property
		String name;
		
		 @Activate
		 public void start(ComponentContext ctx) {
		    	System.out.println("I start now! " + ctx.getProperties());
		 }		
		
	}
	
	
	@Test
	public void testJavaUtilPropertiesConfigLoad() {
		asura.start(new MemoryComponentLoader(), new MemoryComponentLoader(ServiceWithJavaUtilPropertiesXmlConfig.class));
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		ConfigAdminService configAdmin = appServiceSpace.findService(ConfigAdminService.class);
		configAdmin.load(new XmlDirConfigLoader("testconf/xmls"));
		ServiceWithJavaUtilPropertiesXmlConfig serviceWithJavaUtilPropertiesXmlConfig = appServiceSpace.findService(ServiceWithJavaUtilPropertiesXmlConfig.class);
		assertEquals("MyHttpPropertiesTest", serviceWithJavaUtilPropertiesXmlConfig.name);
		assertEquals(5, serviceWithJavaUtilPropertiesXmlConfig.myHttpProperties.size());
		Properties myHttpServer = serviceWithJavaUtilPropertiesXmlConfig.myHttpProperties;
		assertEquals("MyHttpServer_1", myHttpServer.get("serverName"));
		assertEquals("8081", myHttpServer.get("port"));
		assertEquals("10", myHttpServer.get("maxThread"));
		assertEquals("1", myHttpServer.get("minThread"));
		assertEquals("30", myHttpServer.get("sessionTimeout"));
	}
	
	@Test
	public void testXmlMultipleConfigLoad() throws Throwable{
		asura.start(new MemoryComponentLoader(), new MemoryComponentLoader(MyHttpServer.class,ServiceWithListXmlConfig.class,ServiceWithArrayXmlConfig.class,ServiceWithMapXmlConfig.class));
		ServiceSpace appServiceSpace = asura.getComponentManager().getApplicationServiceSpace();
		ConfigAdminService configAdmin = appServiceSpace.findService(ConfigAdminService.class);
		try {
			configAdmin.load(new XmlMultipleConfigLoader("testconf/xfeepAsuraConfigSet.xml"));
		} catch (Throwable e) {
			e.printStackTrace();
			throw e;
		} 
		{
		MyHttpServer myHttpServer = appServiceSpace.findService(MyHttpServer.class);
		assertEquals("MyHttpServer", myHttpServer.serverName);
		assertEquals(8080, myHttpServer.port);
		assertEquals(5, myHttpServer.maxThread);
		assertEquals(2, myHttpServer.minThread);
		assertEquals(300, myHttpServer.sessionTimeout);
		}
		
		{
			ServiceWithListXmlConfig serviceWithListXmlConfig = appServiceSpace.findService(ServiceWithListXmlConfig.class);
			assertEquals("MyHttpServerListTest", serviceWithListXmlConfig.name);
			assertEquals(2, serviceWithListXmlConfig.myhttpServerList.size());
			for (int i = 0; i < 2; i++){
				HttpServerInfo myHttpServer = serviceWithListXmlConfig.myhttpServerList.get(i);
				assertEquals("MyHttpServer_" + (i+1), myHttpServer.serverName);
				assertEquals(8080 + i + 1, myHttpServer.port);
				assertEquals(i+1, myHttpServer.maxThread);
				assertEquals(i+1, myHttpServer.minThread);
				assertEquals(300 + (i+1), myHttpServer.sessionTimeout);
			}
		}
		
		{
			ServiceWithArrayXmlConfig serviceWithArrayXmlConfig = appServiceSpace.findService(ServiceWithArrayXmlConfig.class);
			assertEquals("MyHttpServerArrayTest", serviceWithArrayXmlConfig.name);
			assertEquals(2, serviceWithArrayXmlConfig.myhttpServerArray.length);
			for (int i = 0; i < 2; i++){
				HttpServerInfo myHttpServer = serviceWithArrayXmlConfig.myhttpServerArray[i];
				assertEquals("MyHttpServer_" + (i+1), myHttpServer.serverName);
				assertEquals(8080 + i + 1, myHttpServer.port);
				assertEquals(i+1, myHttpServer.maxThread);
				assertEquals(i+1, myHttpServer.minThread);
				assertEquals(300 + (i+1), myHttpServer.sessionTimeout);
			}
		}
		
		{
			ServiceWithMapXmlConfig serviceWithMapXmlConfig = appServiceSpace.findService(ServiceWithMapXmlConfig.class);
			assertEquals("MyHttpServerListTest", serviceWithMapXmlConfig.name);
			assertEquals(2, serviceWithMapXmlConfig.myhttpServerMap.size());
			for (int i = 0; i < 2; i++){
				HttpServerInfo serverInfo = serviceWithMapXmlConfig.myhttpServerMap.get("MyHttpServer_" + (i+1));
				assertEquals("MyHttpServer_" + (i+1), serverInfo.serverName);
				assertEquals(8080 + i + 1, serverInfo.port);
				assertEquals(i+1, serverInfo.maxThread);
				assertEquals(i+1, serverInfo.minThread);
				assertEquals(300 + (i+1), serverInfo.sessionTimeout);
			}
		}
		
		
	}
	
	@After
	public void tearDown() throws Exception {
		asura.shutdown();
	}
	
}
